#include "timer.h"
#include <cstddef>
#include <cstdint>
#include <functional>
#include <memory>
#include <mutex>
#include <shared_mutex>
#include <vector>
#include "log.h"
#include "util.h"


Timer::Timer(bool recurring, uint64_t ms, TimerManager* manager, std::function<void()> cb)
    :m_recurring(recurring)
    ,m_ms(ms)
    ,m_manager(manager)
    ,m_cb(cb)
{
    m_next = GetCurrentMS() + ms;
}

//next 执行定时任务的时间戳（毫秒）
Timer::Timer(uint64_t next):m_next(next) {}

//取消定时器
bool Timer::cancel()
{
    std::unique_lock<std::shared_mutex> write_lock(m_manager->m_sharedMutex);
    if(m_cb)
    {
        m_cb = nullptr;
        auto it = m_manager->m_timers.find(shared_from_this());
        m_manager->m_timers.erase(it);
        return true;
    }
    return false;
}

//更新定时器执行时间
bool Timer::refresh()
{
    std::unique_lock<std::shared_mutex> write_lock(m_manager->m_sharedMutex);
    if(!m_cb)
    {
        log_error("Timer::refresh m_cb is nullptr");
        return false;
    }

    auto it = m_manager->m_timers.find(shared_from_this());
    if(it == m_manager->m_timers.end())
    {
        log_error("Timer::refresh timer task not find");
        return false;
    }

    m_manager->m_timers.erase(it);
    m_next = GetCurrentMS() + m_ms;
    m_manager->m_timers.insert(shared_from_this());
    return true;
}

//重置定时器
bool Timer::resetTimer(uint64_t ms, bool from_now)
{
    if(ms == m_ms && !from_now)
    {
        return true;
    }

    std::unique_lock<std::shared_mutex> write_lock(m_manager->m_sharedMutex);
    if(!m_cb)
    {
        return false;
    }
    auto it = m_manager->m_timers.find(shared_from_this());
    if(it == m_manager->m_timers.end())
    {
        return false;
    }

    m_manager->m_timers.erase(it);
    uint64_t start = 0;
    if(from_now)
    {
        start = GetCurrentMS();
    }
    else
    {
        start = m_next - m_ms;
    }
    m_ms = ms;
    m_next = start + m_ms;
    //可能会插到定时任务的最前面
    m_manager->addTimerToSet(shared_from_this(), write_lock);

    return true;
}

//set容器需要一个小于号的比较器 按照定任务的执行时间比较
bool Timer::Comparator::operator()(const Timer::ptr &lhs, const Timer::ptr &rhs) const
{
    if(!lhs && !rhs)
    {
        return false;
    }

    if(!lhs)
    {
        return true;
    }
    if(!rhs)
    {
        return false;
    }

    if(lhs->m_next < rhs->m_next)
    {
        return true;
    }
    if(lhs->m_next > rhs->m_next)
    {
        return false;
    }
    return lhs.get() < rhs.get();
}







TimerManager::TimerManager()
{

}
TimerManager::~TimerManager()
{
    
}

//添加定任务
Timer::ptr TimerManager::addTimer(uint64_t ms, std::function<void()> cb, bool recurring)
{
    Timer::ptr timer(new Timer(recurring, ms, this, cb));
    std::unique_lock<std::shared_mutex> write_lock(m_sharedMutex);
    addTimerToSet(timer, write_lock);
    return timer;
}

static void Ontimer(std::weak_ptr<void> weak_cond, std::function<void()> cb)
{
    std::shared_ptr<void> tmp = weak_cond.lock();
    if(tmp) //如果条件还在，就执行回调函数
    {
        cb();
    }
}

//添加条件定任务
Timer::ptr TimerManager::addConditionTimer(uint64_t ms, std::function<void()> cb,  std::weak_ptr<void> weak_cond, bool recurring)
{
    return addTimer(ms, std::bind(&Ontimer, weak_cond, cb), recurring);
}

//返回到最近一个定任务执行的时间间隔（毫秒）
uint64_t TimerManager::getNextTimer()
{
    std::shared_lock<std::shared_mutex> read_lock(m_sharedMutex);
    m_tickled = false;
    if(m_timers.empty())
    {
        return UINT64_MAX;
    }

    //获取timers中第一个任务
    const Timer::ptr& task = *m_timers.begin();
    uint64_t now_ms = GetCurrentMS();
    if(now_ms >= task->m_next)
    {
        return 0;
    }
    else 
    {
        return task->m_next - now_ms;
    }
}
//获取所有超时的定时任务
//cbs 回调函数数组
void TimerManager::listExpiredCb(std::vector<std::function<void()>>& cbs)
{
    uint64_t now_ms = GetCurrentMS();

    std::vector<Timer::ptr> expired;

    {
        std::shared_lock<std::shared_mutex> read_lock(m_sharedMutex);
        if(m_timers.empty())
        {
            return;
        }
    }

    std::unique_lock<std::shared_mutex> write_lock(m_sharedMutex);
    if(m_timers.empty())
    {
        return;
    }

    if((*m_timers.begin())->m_next > now_ms)
    {
        return;
    }

    //找出已经超时的定时任务 的迭代器
    Timer::ptr now_timer(new Timer(now_ms));
    auto it = m_timers.lower_bound(now_timer);
    //如果存在K,lower_bound返回第一个等于k值的迭代器
    //如果不存在K,该迭代器指向刚好大于k的下一个元素。如果参数中传递的键超过了容器中的最大值，则返回end()
    while(it != m_timers.end() && (*it)->m_next == now_ms)
    {
        ++it;
    }
    expired.insert(expired.begin(), m_timers.begin(), it);
    m_timers.erase(m_timers.begin(), it);

    cbs.reserve(expired.size());
    for(auto& task: expired)
    {
        cbs.emplace_back(task->m_cb);
        //如果是循环定时器
        if(task->m_recurring)
        {
            task->m_next = now_ms + task->m_ms;
            m_timers.insert(task);
        }
        else
        {
            task->m_cb = nullptr;   //如果回调函数中有shared_ptr，可以让其引用计数-1
        }
    }
}

//当前是否有定时任务
bool TimerManager::hasTimer()
{
    return false;
}

//将定时器添加到管理器中 判断是否插到了定时器的首部
void TimerManager::addTimerToSet(Timer::ptr val, std::unique_lock<std::shared_mutex>& write_lock)
{
    //插入数据并返回插入数据的位置
    auto it = m_timers.insert(val).first;

    //判断是否插到了定时器的首部
     //m_tickled是为了防止频繁调用onTimerInsertedAtFront 每次在epoll_waite调用之前获取一下最小阻塞时间
    bool at_font = (it == m_timers.begin()) && !m_tickled;
    
    if(at_font)
    {
        m_tickled = true;
    }
    write_lock.unlock();

    if(at_font)
    {
        //因为有一个最小等待时间的任务添加进来了，可能有某些任务要重新设置等待时间
        onTimerInsertedAtFront();
    }
}


// //检测服务器时间是否被调后了
// bool TimerManager::detectClockRollover(uint64_t now_ms)
// {
//     bool rollover = false;
//     //现在的时间小于上次执行时间小一小时
//     if(now_ms < m_previouseTime && now_ms < (m_previouseTime - 60*60*1000))
//     {
//         rollover = true;
//     }
//     m_previouseTime = now_ms;
//     return rollover;

//     return true;
// }